/*
 * @(#)CurrentImpl.java	1.0 2000/12/14
 *
 * Copyright 2000 Thomas Barnekow. All Rights Reserved.
 *
 * This software is the proprietary information of Thomas Barnekow.
 * Use is subject to license terms.
 */

package tb.jots.impl;

import java.lang.ref.*;
import java.util.*;
import tb.jots.*;

/**
 * {@link Current} implementation.
 *
 * @author Thomas Barnekow
 * @version 1.0
 */
public class CurrentImpl implements Current {

  /**
   * Transaction map.
   */
  static final Map m_current = new WeakHashMap();

  /**
   * Transaction's thread reference.
   */
  WeakReference m_thread;

  /**
   * Transaction's {@link Control} object reference.
   */
  ControlImpl m_control;

  /**
   * Don't let'em create instances.
   */
  CurrentImpl(Thread thread) {
    m_thread = new WeakReference(thread);
  }

	/**
	 * Get the current transaction
	 */
	public static synchronized Current getCurrent() {
    Thread thread = Thread.currentThread();
		Current current = (Current) m_current.get(thread);
		if (current == null) {
			current = new CurrentImpl(thread);
			m_current.put(thread, current);
		}
		return current;
	}

	/*
	 * Current operations
	 */

	public void begin()	throws JotsException {
    checkCallingThread();
		if (m_control != null) {
			throw new SubtransactionsUnavailableException();
		}
		setControl(new ControlImpl());
	}

	public void commit(boolean reportHeuristics) throws JotsException {
		if (m_control == null) {
			throw new NoTransactionException();
		}
 		m_control.getTerminator().commit(reportHeuristics);
	}

	public void rollback() throws JotsException {
		if (m_control == null) {
			throw new NoTransactionException();
		}
 		m_control.getTerminator().rollback();
	}

	public void rollbackOnly() throws JotsException {
		if (m_control == null) {
			throw new NoTransactionException();
		}
    m_control.getCoordinator().rollbackOnly();
  }

	public Control getControl() {
		return m_control;
	}

	public int getStatus() throws JotsException {
    if (m_control == null)
      return OTS.STATUS_NO_TRANSACTION;
    else
      return m_control.getCoordinator().getStatus();
  }

  public Control suspend() {
    if (m_control == null) {
      return null;
    }
    Control control = m_control;
    resetTransactionContext();
    return control;
  }

  public void resume(Control control) throws InvalidControlException {
    if (control != null && !(control instanceof ControlImpl)) {
      throw new InvalidControlException();
    }
    setControl((ControlImpl) control);
  }

  /*
   * Implementation-specific operations
   */

  void setControl(ControlImpl control) {
    if (m_control != null) {
      m_control.removeCurrent(this);
    }
    m_control = control;
    if (m_control != null) {
      m_control.addCurrent(this);
    }
  }

 	void resetTransactionContext() {
    setControl(null);
	}

  Thread getThread() {
    return (Thread) m_thread.get();
  }

  void checkCallingThread() throws NoPermissionException {
    if (!Thread.currentThread().equals(getThread()))
      throw new NoPermissionException();
  }
}
